#!/usr/bin/python
"""
ResultMomerizer.py
memorizes results of funcitons.
from aspn python cookbook
"""
# $URL$
# $Id$
# author: yoshiii.yoshiii@googlemail.com
__version__ 	= "$Revision$"

class Memorize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}
    def __call__(self, *args, **kwds):
        if not kwds:
            if not self.memo.has_key(args):
                self.memo[args] = self.fn(*args)
            return self.memo[args]
        return self.fn(*args, **kwds)

class MemorizeWithExceptions:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}
    def __call__(self, *args, **kwds):
        if not kwds:
            try: return self.memo[args]
            except KeyError:
                self.memo[args] = self.fn(*args)
                return self.memo[args]
        return self.fn(*args, **kwds)

class MemorizeMutable:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}
    def __call__(self, *args, **kwds):
        import cPickle
        s = cPickle.dumps(args, 1)+cPickle.dumps(kwds, 1)
        if not self.memo.has_key(s):
            self.memo[s] = self.fn(*args, **kwds)
        return self.memo[s]

def main():
    def fib(n):
        if n < 2: return 1L
        return fib(n-1) + fib(n-2)

#    arg = 331 # maximale anzahl an rekursionen...
#    arg = 100
    arg = 25   # reasonable results!
    import time
    
    print 'plain function'
    print 'map(fib, range(%s))'%arg
    start = time.time()
    map(fib, range(arg))
    t1 = time.time() - start
    print 'time1:', round(t1, 10)


    # funktion muss sich selbst zugewiesen werden!!!
    print 'fib = Memorize(fib)'
    fib = Memorize(fib)
    print 'map(fib, range(%s))'%arg
    start = time.time()
    map(fib, range(arg))
    t2 = time.time() - start
    print 'time:', round(t2, 10)
    print 'speedup: time1/time2 =', round(t1/t2, 4)

if __name__ == '__main__':
    main()
